package com.yunji.base.business;

import com.alibaba.fastjson2.JSONObject;
import com.yunji.base.cache.BaseCache;
import com.yunji.base.domain.LoginStaffDO;
import com.yunji.base.domain.LoginWechatDO;
import com.yunji.base.service.MemberService;
import com.yunji.base.service.StaffService;
import com.yunji.common.base.BaseBusiness;
import com.yunji.common.exception.ServiceException;
import com.yunji.common.model.domain.MemberDO;
import com.yunji.common.model.domain.StaffDO;
import com.yunji.common.utils.SecurityTools;
import com.yunji.common.utils.StringUtils;
import com.yunji.common.utils.bean.BeanUtils;
import com.yunji.common.utils.http.HttpUtils;
import com.yunji.system.context.SystemContext;
import com.yunji.system.convert.LoginInfoConvert;
import com.yunji.system.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.yunji.common.constant.Constants.HEAD_TOKEN;
import static com.yunji.common.constant.General.TOKEN_PREFIX;

/**
 * @Package com.yunji.user.business
 * FileName:	UserLoginBusiness.java
 * Copyright:	Copyright © 2024 云集互联 All Rights Reserved
 * Company:		云集互联
 * @version: 1.0
 * @since: JDK 1.8.0_202
 * Create at:   2024-04-06 23:17:53
 * Description:
 * 用户登录业务处理
 * Modification History:
 * Author					Date					Version         Description
 * -------------------------------------------------------------------------------------
 * HuaAo0803@163.com	2024-04-06 23:17:53		1.0             1.0 Version
 */
@Component
public class UserLoginBusiness extends BaseBusiness {
    @Autowired
    private MemberService memberService;

    @Autowired
    private StaffService staffService;


    @Value("${wechat.wechat.access:https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code}")
    private String wechatAccess;
    @Value("${wechat.member.appid:xxx}")
    private String memberAppid;
    @Value("${wechat.member.secret:xxx}")
    private String memberSecret;

    @Value("${wechat.staff.appid:xxx}")
    private String staffAppid;
    @Value("${wechat.staff.secret:xxx}")
    private String staffSecret;

    @Value("${yunji.user.avatar:https://xxx.packifys.com/profile/upload/2024/02/18/0{}.png}")
    private String avatar;

    private static final String DEFAULT_NICKNAME = "微信用户";

    private static final Long DEFAULT_GENDER = 0L;
    @Autowired
    private TokenService tokenService;

    private void getUserInfo(LoginWechatDO wechat, String keys) {
        String userInfos = wechat.getUserInfo();
        logs.info("[注册]上送用户参数:{}", userInfos);
        Map<String, Object> userInfoMap = JSONObject.parseObject(userInfos);
        if (BeanUtils.isNotNull(userInfoMap)) {
            String nickName = String.valueOf(userInfoMap.get("nickName"));
            Long gender = Long.valueOf(String.valueOf(userInfoMap.get("gender")));
            logs.info("[注册]用户别名:{},用户性别:{}", nickName, gender);
            wechat.setNickName(nickName);
            wechat.setGender(gender);
            if (BeanUtils.isNotNull(nickName) && BeanUtils.isNotNull(gender)) {
                return;
            }
        }

        String encrypt = wechat.getUserinfoEncryptedData();
        String iv = wechat.getUserinfoEncryptedData();
        logs.info("[注册]用户加密数据:{},加密偏移量:{}", encrypt, iv);
        if (BeanUtils.isNull(encrypt) || BeanUtils.isNull(iv)) {
            return;
        }
        JSONObject userInfo = SecurityTools.decryptAes(wechat.getUserinfoEncryptedData(), keys, wechat.getUserinfoIv());
        logs.info("[注册]解密用户信息：{}", userInfo);
        if (BeanUtils.isNull(userInfos)) {
            return;
        }
        String nickName = userInfo.getString("nickName");
        Long gender = Long.valueOf(userInfo.getString("gender"));
        logs.info("[注册]用户别名:{},用户性别:{}", nickName, gender);
        wechat.setNickName(nickName);
        wechat.setGender(gender);
    }


    private MemberDO registerUmsMember(LoginWechatDO wechat, String keys, String openid, String unionid) {
        logs.info("注册用户的入参参数-->sessionKey:{}", keys);
        logs.info("注册用户的入参参数------>openid:{}", openid);
        logs.info("注册用户的入参参数----->unionid:{}", unionid);

        //注册 -
        MemberDO temp = new MemberDO();
        temp.setCreateTime(new Date());
        //帐号启用状态:0->正常；1->禁用
        temp.setStatus(0L);
        temp.setPhone(wechat.getPhone());

        getUserInfo(wechat, keys);
        Long gender = wechat.getGender();
        String nickName = wechat.getNickName();
        logs.info("[注册]用户昵称:{}", nickName);
        logs.info("[注册]用户性别:{}", gender);


        temp.setName(BeanUtils.isNotNull(nickName) ? nickName : DEFAULT_NICKNAME);
        temp.setGender(BeanUtils.isNotNull(gender) ? gender : DEFAULT_GENDER);

        // 使用当前时间获取头像
        long time = System.currentTimeMillis();
        long i = time % 6;
        temp.setAvatar(StringUtils.format(avatar, i));

        temp.setOpenid(openid);
        temp.setUnionid(unionid);
        logs.info("[注册] temp : {}", temp);
        memberService.insertMember(temp);
        return temp;
    }

    /**
     * @return Map<String, Object>
     * @Title loginWechat
     * @Desc 微信用户登录
     * @Date 2024-04-07 14:31:57
     * @Param wechat 微信登录信息
     */
    public Map<String, Object> loginWechat(LoginWechatDO wechat) {
        try {
            logs.info("[微信登录] 参数: {}", wechat);
            //校验参数
            Assert.isTrue((BeanUtils.isNotNull(wechat.getCode())), "wechat code ie empty");

            // 请求微信小程序API获取openid & unionid
            String url = String.format(wechatAccess, memberAppid, memberSecret, wechat.getCode());

            logs.info("微信登录 API : url {}", url);
            String s = HttpUtils.get(url);
            JSONObject result = JSONObject.parseObject(s);
            logs.info("微信登录 API : 返回 {}", result);

            Assert.isTrue(result.containsKey("session_key"), StringUtils.format("code :[{}], errmsg :[{}]", result.getString("errcode"), result.getString("errmsg")));

            // 解析获取用户微信相关信息(country/unionid/gender/province/city/avatarUrl/openid/nickName/language)
            String keys = result.getString("session_key");
            String openid = result.getString("openid");
            String unionid = result.getString("unionid");

            //查询登录的手机号
            JSONObject phoneInfo = SecurityTools.decryptAes(wechat.getPhoneEncryptedData(), keys, wechat.getPhoneIv());
            String phone = BeanUtils.isNull(phoneInfo) ? "" : phoneInfo.getString("phoneNumber");
            wechat.setPhone(phone);
//            JSONObject object1 = SecurityTools.decryptAes(wechat.getUserinfoEncryptedData(), keys, wechat.getUserinfoIv());
//            logs.info("解析获取用户: [{}]", object1);

            MemberDO member = memberService.selectMember(phone);
            if(member!=null){
                logs.info("[登录] 开始 : {} {} {} {}", member, wechat, openid, unionid);
                member.setOpenid(openid);
                memberService.updateOpenId(phone, openid);
                //判断手机号和openid是否唯一
                MemberDO openIdAndPhone = memberService.selectMember(phone);
                if (openIdAndPhone == null) {
                    //对openid相同的手机号进行二次注册
                    logs.info("[二次注册] 开始 : {} {} {} {}", member, wechat, openid, unionid);
                    member = registerUmsMember(wechat, keys, openid, unionid);
                }
                logs.info("[登录] 成功 : {}", member);
            }else {
                //判断Member 注册 / 登录
                logs.info("[注册] 开始 :==================> ");
                member = registerUmsMember(wechat, keys, openid, unionid);
                logs.info("[注册] 成功 : {}", member);
            }
            //判断是否能进行登录
            Assert.isTrue((member.getStatus() == 0L), StringUtils.format("您的账号已被禁止登录[{}]", member.getPhone()));
            //生成token
            String token = tokenService.createToken(LoginInfoConvert.convertLoginInfo(member));
            //定义返回结果集
            Map<String, Object> map = new HashMap<>();
            map.put("userId", member.getId());
            map.put("userInfo", member);
            map.put("tokenHead", TOKEN_PREFIX);
            map.put("token", token);
            logs.info("[微信登录/注册] end : {}", map);
            return map;
        } catch (Exception e) {
            logs.info("[登录/注册] param {} apiMallError : {}", wechat, e.getMessage());
            throw new ServiceException("微信登录错误：" + e.getMessage());
        }
    }

    /**
     * @return Map<String, Object>
     * @Title loginStaff
     * @Desc 员工用户登录
     * @Date 2024-04-07 14:31:37
     * @Param param 员工登录信息
     */
    public Map<String, Object> loginStaff(LoginStaffDO param) {
        // 根据员工id获取员工信息，然后判断密码
        StaffDO staff = staffService.getByPhone(param.getStaffId());
        Assert.isTrue(BeanUtils.isNotNull(staff), "该员工账号不存在");

        Assert.isTrue(BCrypt.checkpw(param.getStaffPwd(), staff.getStaffPwd()), "密码错误");

        Assert.isTrue((staff.getStatus() != 0), "该员工不允许登录");
        // String token = userToken.setStaffUser(staff);
        String token = tokenService.createToken(LoginInfoConvert.convertLoginInfo(staff));
        //定义返回结果集
        Map<String, Object> map = new HashMap<>();
        staff.setStaffPwd(null);
        map.put("userInfo", staff);
        map.put("tokenHead", TOKEN_PREFIX);
        map.put("token", token);
        logs.info("员工登录: {}", map);
        return map;
    }

    /**
     * @param wechat 微信信息
     * @Title loginStaffByWechat
     * @Desc 员工端微信登陆
     * @Date 2024-09-06 11:58:15.146
     * @Return Map<String, Object> 员工信息
     */
    public Map<String, Object> loginStaffByWechat(LoginWechatDO wechat) {
        logs.info("[微信登录] 参数: {}", wechat);
        //校验参数 前端通过wx.login 获取的code
        Assert.isTrue((BeanUtils.isNotNull(wechat.getCode())), "wechat code ie empty");


        //通过小程序appid+小程序appsecret+登陆code去获取session_key 和 openid
        String url = String.format(wechatAccess, staffAppid, staffSecret, wechat.getCode());

        logs.info("微信登陆 API ：url {}", url);
        String s = HttpUtils.get(url);
        JSONObject result = JSONObject.parseObject(s);
        logs.info("微信登陆 API ：返回 {}", result);

        //校验是否返回需要参数
        Assert.isTrue(result.containsKey("session_key"), StringUtils.format("code :[{}], errmsg :[{}]", result.getString("errcode"), result.getString("errmsg")));

        //解析微信登陆信息
        String keys = result.getString("session_key");
        String openid = result.getString("openid");
        logs.info("员工openid[{}]", openid);
        String unionid = result.getString("unionid");
        logs.info("员工unionid[{}]", unionid);

        //查询登陆的手机号
        JSONObject phoneInfo = SecurityTools.decryptAes(wechat.getPhoneEncryptedData(), keys, wechat.getPhoneIv());
        String phone = BeanUtils.isNull(phoneInfo) ? "" : phoneInfo.getString("phoneNumber");
        logs.info("员工手机号[{}]", phone);

//        JSONObject object1 = SecurityTools.decryptAes(wechat.getUserinfoEncryptedData(),keys,wechat.getUserinfoEncryptedData()) ;
//        logs.info("解析获取员工：【{}】",object1);
        StaffDO staff = staffService.getByPhone(phone);
        //判断是否是员工账号
        Assert.isTrue(BeanUtils.isNotNull(staff), StringUtils.format("该手机号非员工账号,请联系管理员配置"));
        //判断是否能进行登录
        Assert.isTrue((staff.getStatus() == 1L), StringUtils.format("账号异常，请联系人工客服"));

        //修改员工信息 进行openid的跟新
        StaffDO param = new StaffDO();
        param.setId(staff.getId());
        param.setOpenid(openid);
        param.setUnionid(unionid);
        Assert.isTrue(staffService.update(param), "修改员工信息失败");
        //生成token
        String token = tokenService.createToken(LoginInfoConvert.convertLoginInfo(staff));
        //定义返回结果集
        Map<String, Object> map = new HashMap<>();
        map.put("userId", staff.getId());
        map.put("userInfo", staff);
        map.put("tokenHead", TOKEN_PREFIX);
        map.put("token", token);
        return map;
    }

    /**
     * @return Member 微信用户信息
     * @Title getWechatUser
     * @Desc 获取微信用户信息
     * @Date 2024-04-07 15:30:12
     */
    public MemberDO getWechatUser() {
        return BaseCache.getMember(SystemContext.getUserId());
    }

    /**
     * @return JSONObject Token信息
     * @Title getWechatToken
     * @Desc 获取微信用户Token信息
     * @Date 2024-04-07 15:30:34
     */
    public JSONObject getWechatToken(String phone) {
        JSONObject jsonObject = new JSONObject();
        MemberDO member = memberService.selectMember(phone);
        // 生成token
        String token = tokenService.createToken(LoginInfoConvert.convertLoginInfo(member));
        jsonObject.put(HEAD_TOKEN, TOKEN_PREFIX + token);
        return jsonObject;
    }
}
